/*
 * Copyright (C) 2022 panpf <panpfpanpf@outlook.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.panpf.sketch.sample.ui.test.fetcher

import android.app.Application
import android.content.ContentUris
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.provider.MediaStore
import androidx.lifecycle.viewModelScope
import com.github.panpf.sketch.fetch.newAppIconUri
import com.github.panpf.sketch.fetch.newResourceUri
import com.github.panpf.sketch.resources.AssetImages
import com.github.panpf.sketch.sample.R
import com.github.panpf.sketch.sample.ui.base.LifecycleAndroidViewModel
import com.github.panpf.sketch.sample.util.versionCodeCompat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class FetcherTestViewModel(application1: Application) : LifecycleAndroidViewModel(application1) {

    private val _data = MutableStateFlow<ImageFromData?>(null)
    val data: StateFlow<ImageFromData?> = _data

    init {
        load()
    }

    private fun load() {
        viewModelScope.launch {
            val localFirstPhotoPath = loadLocalFirstPhotoPath()
            val localSecondPhotoUri = loadLocalSecondPhotoUri()
            val headerUserPackageInfo = loadUserAppPackageInfo(true)
            val datas = ArrayList<Pair<String, String>>().apply {
                add("HTTP" to "http://img.panpengfei.com/sample_antelope.jpg")
                add("HTTPS" to "https://images.unsplash.com/photo-1431440869543-efaf3388c585?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&s=8b00971a3e4a84fb43403797126d1991%22")
                if (localSecondPhotoUri != null) {
                    add("CONTENT" to localSecondPhotoUri.toString())
                }
                if (localFirstPhotoPath != null) {
                    add("FILE" to localFirstPhotoPath)
                }
                add("ASSET" to AssetImages.statics.first().uri)
                add("RES_ID" to newResourceUri(R.mipmap.ic_launcher))
                add("RES_NAME" to newResourceUri("drawable", "bg_circle_accent"))
                add(
                    "APP_ICON" to newAppIconUri(
                        headerUserPackageInfo.packageName,
                        headerUserPackageInfo.versionCodeCompat
                    )
                )
                add("BASE64" to BASE64_IMAGE)
            }
            val uris = datas.map { it.second }.toTypedArray()
            val titles = datas.map { it.first }.toTypedArray()
            _data.value = ImageFromData(titles, uris)
        }
    }

    private suspend fun loadUserAppPackageInfo(fromHeader: Boolean): PackageInfo {
        return withContext(Dispatchers.IO) {
            val packageList =
                application1.packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS)
            (if (fromHeader) {
                packageList.find {
                    it.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0
                }
            } else {
                packageList.findLast {
                    it.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0
                }
            } ?: application1.packageManager.getPackageInfo(application1.packageName, 0))
        }
    }

    private suspend fun loadLocalFirstPhotoPath(): String? {
        return withContext(Dispatchers.IO) {
            val cursor = application1.contentResolver.query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                arrayOf(MediaStore.Images.Media.DATA),
                null,
                null,
                MediaStore.Images.Media.DATE_TAKEN + " DESC" + " limit " + 0 + "," + 1
            )
            var imagePath: String? = null
            cursor?.use {
                if (cursor.moveToNext()) {
                    imagePath =
                        cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
                }
            }
            imagePath
        }
    }

    private suspend fun loadLocalSecondPhotoUri(): Uri? {
        return withContext(Dispatchers.IO) {
            val cursor = application1.contentResolver.query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                arrayOf(MediaStore.Images.Media._ID),
                null,
                null,
                MediaStore.Images.Media.DATE_TAKEN + " DESC" + " limit " + 1 + "," + 1
            )
            var imageId: Long? = null
            cursor?.use {
                if (cursor.moveToNext()) {
                    imageId =
                        cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
                }
            }
            if (imageId != null) {
                ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageId!!)
            } else {
                null
            }
        }
    }

    class ImageFromData(val titles: Array<String>, val uris: Array<String>)

    companion object {
        const val BASE64_IMAGE =
            ""
    }
}